package group2.core.database;

import group2.core.entities.CamelUser;
import group2.core.entities.CamelUser_;
import group2.core.entities.Comment;
import group2.core.entities.Comment_;
import group2.core.entities.Post;
import group2.core.entities.Post_;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

/**
 * A class for the extra utilities we need from the database, which do not
 * fit in the interface IJpaCtrl.
 * 
 * @author ludwigk
 */
public class DatabaseUtil {

    private static DatabaseUtil instance;

    private EntityManagerFactory emf = Persistence.createEntityManagerFactory("webblog_pu");

    private DatabaseUtil() {
    }

    public static DatabaseUtil getInstance() {
        if (instance == null) {
            instance = new DatabaseUtil();
        }
        return instance;
    }
    
    /**
     * Looks in the database if a user with this password exists.
     * @param userName The username
     * @param password The password
     * @return true if this userName has this password, false else.
     */
    public boolean verifyPassword(String userName, String password) {
        CamelUser c = findCamelUserByName(userName);
        return c.getPassword().equals(password);
    }

    /**
     * Finds a user from a username.
     * @param userName The user we're looking for.
     * @return the CamelUser with this userName, null if not existing. 
     */
    public CamelUser findCamelUserByName(String userName) {

        EntityManager em = emf.createEntityManager();
        CamelUser user = null;

        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<CamelUser> query = builder.createQuery(CamelUser.class);
        Root<CamelUser> cU = query.from(CamelUser.class);
        Path<String> uName = cU.get(CamelUser_.userName);
        Predicate cond1 = builder.equal(uName, userName);
        query.where(cond1);
        TypedQuery<CamelUser> q = em.createQuery(query);
        try {

            user = q.getSingleResult();
            return user;

        } catch (NoResultException e) {

            return user;
        }
    }

    /**
     * Finds the latest comments, returning a certain maximum results.
     * @param results Max amount of comments.
     * @return A list of comments.
     */
    public List<Comment> getLatestComments(int results) {
        EntityManager em = emf.createEntityManager();
        // Get the comments orderd by Comment.date
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<Comment> query = builder.createQuery(Comment.class);
        Root<Comment> comment = query.from(Comment.class);
        query.select(comment);
        query.orderBy(builder.desc(comment.get(Comment_.date)));

        TypedQuery<Comment> q = em.createQuery(query);

        if (results == -1) {
            results = q.getResultList().size();
        } else if (results > q.getResultList().size()) {
            results = q.getResultList().size();
        }

        //Returns the 6 first elements 
        return q.getResultList().subList(0, results);
    }
    
    

    /**
     * Finds the latest comments, returning a certain maximum results.
     * @param results Max amount of comments.
     * @return A list of comments.
     */
    public List<Post> getLatestPosts(int results) {
        EntityManager em = emf.createEntityManager();
        // Get the comments orderd by Comment.date
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<Post> query = builder.createQuery(Post.class);
        Root<Post> post = query.from(Post.class);
        query.select(post);
        query.orderBy(builder.desc(post.get(Post_.date)));

        TypedQuery<Post> q = em.createQuery(query);

        try {
            if (results == -1) {
                results = q.getResultList().size();
            } else if (results > q.getResultList().size()) {
                results = q.getResultList().size();
            }

            //Returns the 6 first elements 
            return q.getResultList().subList(0, results);
        }
        catch(IllegalStateException  e){
            List<Post> list = new ArrayList<Post>();
            return list;
        }
    }
    
    /**
     * Checks if the userName and email exists in the database.
     * @param userName
     * @param email
     * @return true if userName and email are unique.
     */
    public boolean isUnique(String userName, String email) {
        EntityManager em = emf.createEntityManager();
        List<CamelUser> list = null;

        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<CamelUser> query = builder.createQuery(CamelUser.class);
        Root<CamelUser> cU = query.from(CamelUser.class);
        Path<String> uName = cU.get(CamelUser_.userName);
        Path<String> eMail = cU.get(CamelUser_.email);
        Predicate cond1 = builder.equal(uName, userName);
        Predicate cond2 = builder.equal(eMail, email);
        query.where(builder.or(cond1, cond2));

        TypedQuery<CamelUser> q = em.createQuery(query);

        //if no NoResultException there are atleast a user with the checked email or userName
        list = q.getResultList();
        return list.isEmpty();
    }
}
